﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;

namespace CameraDownloader
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        
        private string picturesPath;
        private string cardPath;
        private string metadata;
        private bool overwrite;
        private bool picsDone;
        private bool moviesDone;
        private bool move = true;

        public Window1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Upon loading, make sure that the path displayed is valid
        /// </summary>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            picturesPath = Properties.Settings.Default.PicturePath;

            if (!verifyPath(picturesPath))
            {
                return;
            }

            folderBox.Text = Properties.Settings.Default.LastPath;
        }

        private void okBtn_Click(object sender, RoutedEventArgs e)
        {
            // Need to have something as a path
            if (folderBox.Text.Length < 1)
            {
                System.Windows.MessageBox.Show("No folder selected", "Selection Error", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                return;
            }
            
            // Save the path for next time
            picturesPath = folderBox.Text;
            Properties.Settings.Default.LastPath = picturesPath;
            Properties.Settings.Default.Save();

            cardPath = Properties.Settings.Default.CardPath;

            metadata = eventBox.Text;

            if (!verifyPath(cardPath))
            {
                return;
            }

            // Get all the files and calculate the progress bar
            string[] pictures = Directory.GetFiles(cardPath, "*.jpg");
            string[] movies = Directory.GetFiles(cardPath, "*.avi");
            string[] remove = Directory.GetFiles(cardPath, "*.thm");

            progressBar1.Maximum = pictures.Length + movies.Length + remove.Length;

            // See if we're moving or just copying
            if (moveCheck.IsChecked == false)
            {
                move = false;
            }

            // See if we want to overwrite existing files
            if (overwriteCheck.IsChecked == true)
            {
                overwrite = true;
            }

            // Start the picture downloading process in a new thread
                ThreadStart picturesProcess = delegate
                {
                    if (pictures.Length > 0)
                    {
                        processCamera(pictures);
                        picsDone = true;
                        CompleteDownload();
                    }
                    else
                    {
                        picsDone = true;
                    }
                };

            // Start the clips downloading process in a new thread
                ThreadStart moviesProcess = delegate
                {
                    if (movies.Length > 0)
                    {
                        processCamera(movies);
                        if (remove.Length > 0) // this is always true for my camera
                        {
                            Remove(remove);
                        }
                        moviesDone = true;
                        CompleteDownload();
                    }
                    else
                    {
                        moviesDone = true;
                    }
                };

                this.okBtn.IsEnabled = false;

                new Thread(picturesProcess).Start();
                new Thread(moviesProcess).Start();
        }

        /// <summary>
        /// Checks if a given path exists
        /// </summary>
        private bool verifyPath(string path)
        {
            if (!Directory.Exists(path))
            {
                System.Windows.MessageBox.Show(String.Format("Cannot access '{0}'", path), "Folder Error",
                    MessageBoxButton.OK, MessageBoxImage.Error);
                return false;
            }

            return true;
        }

        /// <summary>
        /// Core method that actually does the transfer
        /// </summary>
        /// <param name="files">The array of filenames</param>
        private void processCamera(string[] files)
        {
            foreach (string f in files)
            {
                int fileIndex = f.LastIndexOf('\\') + 1;
                string file = f.Substring(fileIndex, f.Length - fileIndex);
             
                // Create the destination folder
                string folder = System.IO.Path.Combine(picturesPath, File.GetCreationTime(f).ToString("yyyy-MM-dd"));

                if (!String.IsNullOrEmpty(metadata))
                {
                    folder += String.Format(" - {0}", metadata);
                }

                if (!Directory.Exists(folder))
                {
                    Directory.CreateDirectory(folder);
                }

                // Move or Copy
                try
                {
                    string dest = System.IO.Path.Combine(folder, file);
                    if (File.Exists(dest) && overwrite)
                    {
                        File.Delete(dest);
                    }

                    if (!File.Exists(dest))
                    {

                        if (move)
                        {
                            File.Move(f, dest);
                        }
                        else
                        {
                            File.Copy(f, dest);
                        }
                    }
                }
                catch (IOException ex)
                {
                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
                        new Action(
                            delegate()
                            {
                                System.Windows.MessageBox.Show(ex.Message, "Download Error", MessageBoxButton.OK, MessageBoxImage.Error);
                            }
                    ));
                }
                UpdateProgress();
            }
        }

        /// <summary>
        /// Removes files.
        /// </summary>
        /// <param name="files">The array of files.</param>
        private void Remove(string[] files)
        {
            foreach (string f in files)
            {
                File.Delete(f);
                UpdateProgress();
            }
        }

        /// <summary>
        /// Updates the progress bar
        /// </summary>
        private void UpdateProgress()
        {
            progressBar1.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
                new Action(
                    delegate()
                    {
                        ++progressBar1.Value;
                    }
            ));
        }

        /// <summary>
        /// Browse for the destination root folder
        /// </summary>
        private void browseBtn_Click(object sender, RoutedEventArgs e)
        {
            FolderBrowserDialog fd = new FolderBrowserDialog();
            fd.RootFolder = Environment.SpecialFolder.MyPictures;
            fd.ShowDialog();
            folderBox.Text = fd.SelectedPath;
        }

        /// <summary>
        /// Go to the destination folder of the pictures
        /// </summary>
        private void galleryBtn_Click(object sender, RoutedEventArgs e)
        {
            Process browser = new Process();
            browser.StartInfo.FileName = picturesPath;
            browser.Start();

            // Close the application since we don't need it anymore
            System.Environment.Exit(0);
        }

        private void CompleteDownload()
        {
            if (picsDone && moviesDone)
            {
                this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
                    new Action(
                        delegate()
                        {
                            this.okBtn.Visibility = Visibility.Hidden;
                            this.galleryBtn.Visibility = Visibility.Visible;

                            this.galleryBtn.IsEnabled = true;
                            System.Windows.MessageBox.Show("Done", "Download Complete", MessageBoxButton.OK, MessageBoxImage.Information);
                        }
                ));
            }
        }
    }
}
